1200 // Boot loader.
1201 //
1202 // Part of the boot sector, along with bootasm.S, which calls bootmain().
1203 // bootasm.S has put the processor into protected 32-bit mode.
1204 // bootmain() loads an ELF kernel image from the disk starting at
1205 // sector 1 and then jumps to the kernel entry routine.
1206 
1207 #include "types.h"
1208 #include "elf.h"
1209 #include "x86.h"
1210 
1211 #define SECTSIZE  512
1212 
1213 void readseg(uchar*, uint, uint);
1214 
1215 void
1216 bootmain(void)
1217 {
1218   struct elfhdr *elf;
1219   struct proghdr *ph, *eph;
1220   void (*entry)(void);
1221   uchar* va;
1222 
1223   elf = (struct elfhdr*)0x10000;  // scratch space
1224 
1225   // Read 1st page off disk
1226   readseg((uchar*)elf, 4096, 0);
1227 
1228   // Is this an ELF executable?
1229   if(elf->magic != ELF_MAGIC)
1230     return;  // let bootasm.S handle error
1231 
1232   // Load each program segment (ignores ph flags).
1233   ph = (struct proghdr*)((uchar*)elf + elf->phoff);
1234   eph = ph + elf->phnum;
1235   for(; ph < eph; ph++) {
1236     va = (uchar*)(ph->va & 0xFFFFFF);
1237     readseg(va, ph->filesz, ph->offset);
1238     if(ph->memsz > ph->filesz)
1239       stosb(va + ph->filesz, 0, ph->memsz - ph->filesz);
1240   }
1241 
1242   // Call the entry point from the ELF header.
1243   // Does not return!
1244   entry = (void(*)(void))(elf->entry & 0xFFFFFF);
1245   entry();
1246 }
1247 
1248 
1249 
1250 void
1251 waitdisk(void)
1252 {
1253   // Wait for disk ready.
1254   while((inb(0x1F7) & 0xC0) != 0x40)
1255     ;
1256 }
1257 
1258 // Read a single sector at offset into dst.
1259 void
1260 readsect(void *dst, uint offset)
1261 {
1262   // Issue command.
1263   waitdisk();
1264   outb(0x1F2, 1);   // count = 1
1265   outb(0x1F3, offset);
1266   outb(0x1F4, offset >> 8);
1267   outb(0x1F5, offset >> 16);
1268   outb(0x1F6, (offset >> 24) | 0xE0);
1269   outb(0x1F7, 0x20);  // cmd 0x20 - read sectors
1270 
1271   // Read data.
1272   waitdisk();
1273   insl(0x1F0, dst, SECTSIZE/4);
1274 }
1275 
1276 // Read 'count' bytes at 'offset' from kernel into virtual address 'va'.
1277 // Might copy more than asked.
1278 void
1279 readseg(uchar* va, uint count, uint offset)
1280 {
1281   uchar* eva;
1282 
1283   eva = va + count;
1284 
1285   // Round down to sector boundary.
1286   va -= offset % SECTSIZE;
1287 
1288   // Translate from bytes to sectors; kernel starts at sector 1.
1289   offset = (offset / SECTSIZE) + 1;
1290 
1291   // If this is too slow, we could read lots of sectors at a time.
1292   // We'd write more to memory than asked, but it doesn't matter --
1293   // we load in increasing order.
1294   for(; va < eva; va += SECTSIZE, offset++)
1295     readsect(va, offset);
1296 }
1297 
1298 
1299 
